﻿
/*
 * Copyright (C) Han Wei
 */


using System;
using System.Collections.Generic;
using System.Threading;
using System.Data;
using System.Linq;


using BSvr.Model;


namespace BSvr.PluginAPI
{
    /// <summary>
    /// 批处理服务器抽象插件类
    /// </summary>
    public abstract class BatchingPlugin:IPlugin
    {
        protected Dictionary<string, Batch> _runnings = new Dictionary<string, Batch>();
        protected bool _isrunning = false;

        #region IPlugin 成员
        public string PluginNo { get; set; }

        public string CurrentDirectory { get; set; }

        public bool IsRunning { get { return this._isrunning; } }

        public abstract OpRst<string> Excute(string cmd, List<string> cmdarg);

        public abstract OpRst<string> Query(string query, List<string> queryarg);

        public abstract OpRst<DataTable> ExcuteConsole(string cmd, List<string> cmdarg);

        public void Init(string plugino,string currentdir) {
            this.PluginNo = plugino;
            this.CurrentDirectory = currentdir;
        }
      
        public OpRst<string> Start()
        {
            this._isrunning = true;
            return new OpRst<string>(true, "启动");
        }

        public OpRst<string> End()
        {
            this._isrunning = false;
            foreach (KeyValuePair<string, Batch> item in _runnings) {
                try
                {
                    item.Value.End();
                }
                catch { }
            }
            return new OpRst<string>(true, "终止");
        }

        public abstract string Information{get;}

        #endregion

        #region 内部类型
        /// <summary>
        /// 批次类型
        /// </summary>
        public abstract class Batch
        {
            protected int    _total = 0;
            protected int _current = 0;
            protected string _batchno = "";
            protected string _operator = "";
            protected uint _workercount = 1;
            protected STATE _state = STATE.INIT;
            protected List<Thread> _lstthr = new List<Thread>();
            protected BatchingPlugin _parent = null;
            protected Thread _mainThd = null;

            /// <summary>
            /// 批次号
            /// </summary>
            public string BatchNo { get { return this._batchno; } }

            /// <summary>
            /// 操作员
            /// </summary>
            public string Operator { get { return this._operator; } }

            /// <summary>
            /// 状态
            /// </summary>
            public STATE State { get { return this._state; } }

            /// <summary>
            /// 要处理的总记录数
            /// </summary>
            public int Total { get { return this._total; } }

            /// <summary>
            /// 当前已经处理的记录数
            /// </summary>
            public int Current { get { return this._current; } }

            public Thread MainThread { get { return this._mainThd; } }

            /// <summary>
            /// 构造方法
            /// </summary>
            /// <param name="batchno">批次号</param>
            /// <param name="optor">操作者</param>
            /// <param name="state">批次状态</param>
            public Batch(BatchingPlugin parent,string batchno, string optor, STATE state)
            {
                this._parent = parent;
                this._batchno = batchno;
                this._operator = optor;
                this._state = state;
                this._mainThd = new Thread(new ThreadStart(_Start));
            }

            /// <summary>
            /// 工作线程数量
            /// </summary>
            public uint WorkerCount { get { return this._workercount; } set { this._workercount = value; } }

            /// <summary>
            /// 获取下个要处理的数据项
            /// </summary>
            /// <returns></returns>
            public abstract DataItem GetNextItem();

            /// <summary>
            /// 启动操作，主线程内执行
            /// </summary>
            private void _Start() {
                try
                {
                    this.LoadData();
                }
                catch (Exception ex)
                {
                    throw ex;
                }

                string errstr = "";
                this._parent._runnings.Add(this._batchno, this);                    // 加入运行队列
                SetState(STATE.RUNNING);                                            // 批次状态变为运行

                try
                {
                    for (uint i = 0; i < this._workercount; i++)
                    {                  // 创建处理线程
                        Thread thr = new Thread(new ThreadStart(this.Handle));
                        thr.Name = this.BatchNo + "_" + i.ToString();
                        _lstthr.Add(thr);
                        thr.Start();
                    }
                }
                catch (Exception ex)
                {                                              // 启动失败
                    this._parent._runnings.Remove(this._batchno);                   // 恢复成启动前的状态
                    SetState(STATE.INIT);
                    throw ex;
                }

                for (uint i = 0; i < this._workercount; i++)
                {                      // Join所有处理线程
                    try
                    {
                        _lstthr[(int)i].Join();
                    }
                    catch (Exception ex)
                    {
                        errstr += ("线程" + _lstthr[(int)i].Name + "Join异常，原因：" + ex.Message);
                    }
                }

                if (!string.IsNullOrEmpty(errstr))
                    throw new Exception(errstr);

                try
                {
                    this._parent._runnings.Remove(this.BatchNo);                    // 从运行队列中清除
                    SetState(STATE.FINISH);                                         // 修改批次状态

                    if (this.Current != this.Total)
                    {
                        throw new Exception("批次" + BatchNo + "处理完成时，要处理数量和已处理数量不一致，要处理" + this.Total.ToString() + "条，已处理" + this.Current.ToString());
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("批次" + BatchNo + "设置完成状态时异常,异常内容：" + ex.Message);
                }
            }

            /// <summary>
            /// 批次启动
            /// </summary>
            /// <exception cref="Exception">异常</exception>
            public void Start() {
                this.MainThread.Start();
            }
             
            /// <summary>
            /// 批处理停止
            /// </summary>
            public void End() {
                //foreach (Thread item in this._lstthr) {                   // 终止所有执行线程
                //    if (item.ThreadState == ThreadState.Running)
                //    {
                //        try
                //        {
                //            item.Abort();
                //        }
                //        catch { }
                //    }
                //}
                try
                {
                    this.MainThread.Abort();                                // 终止主线程
                }
                catch { }
            }

            /// <summary>
            /// 初始化待处理数据项集合
            /// </summary>
            /// <param name="inits">初始化时必要的参数</param>
            protected abstract void LoadData();

            /// <summary>
            /// 处理者，要是线程安全的
            /// </summary>
            protected abstract void Handle();

            /// <summary>
            /// 设置批次状态
            /// </summary>
            /// <param name="state">新的批次状态</param>
            /// <exception cref="Exception">异常</exception>
            protected abstract void SetState(STATE state);
            
            #region 内部类型
            /// <summary>
            /// 批次状态
            /// </summary>
            public enum STATE
            {
                INIT,
                RUNNING,
                STOP,
                FINISH
            }

            /// <summary>
            /// 数据项
            /// </summary>
            public class DataItem {
                /// <summary>
                /// 状态
                /// </summary>
                public STATE State { get; set; }

                /// <summary>
                /// 数据
                /// </summary>
                public object Data { get; set; }

                /// <summary>
                /// 构造方法
                /// </summary>
                /// <param name="data">数据</param>
                /// <param name="state">处理状态</param>
                public DataItem(object data, STATE state) {
                    this.Data = data;
                    this.State = state;
                }

                public enum STATE
                {
                    INIT,
                    FAIL,
                    SUCCESS
                }
            } 
            #endregion
        }
        #endregion
    }
}
